#include "BaseFun.h"
#include "HelpFun.h"
#include "DumpLog.h"
namespace Solver
{

BaseFun::BaseFun(uint32_t dim, FunType_E type, DifficultyLevel_E level, uint32_t errorDim, const std::string &name, const std::string &description):id_(0), type_(type), level_(level), errorDim_(errorDim), name_(name), description_(description), passY_(std::numeric_limits<value_t>::max()), bestY_(0)
{
    bestX_.resize(dim);
}

BaseFun::~BaseFun()
{

}

void BaseFun::setID(uint32_t id)
{
    id_ = id;
}

uint32_t BaseFun::getID() const
{
    return id_;
}

uint32_t BaseFun::getDim() const
{
    return bestX_.size();
}

uint32_t BaseFun::getErrorDim() const
{
    return errorDim_;
}

FunType_E BaseFun::getType() const
{
    return type_;
}

DifficultyLevel_E BaseFun::getLevel() const
{
    return level_;
}

std::string BaseFun::getLevelStr() const
{
    //1.
    if (level_ == DifficultyLevel_E::Easy_E)
    {
        return "容易";
    }

    //2.
    return level_ == DifficultyLevel_E::Hard_E ? "困难" : "中等";
}

const std::string &BaseFun::getName() const
{
    return name_;
}

const std::string &BaseFun::getDescription() const
{
    return description_;
}

value_t BaseFun::getPassY() const
{
    return passY_;
}

value_t BaseFun::getBestY() const
{
    return bestY_;
}

const VectorXd_t &BaseFun::getBestX()
{
    return bestX_;
}

const VectorXd_t &BaseFun::getMinX() const
{
    return minX_;
}

const VectorXd_t &BaseFun::getMax() const
{
    return maxX_;
}

bool BaseFun::setXRange(value_t minX, value_t maxX)
{
    //1.
    minX_.resize(bestX_.size());
    maxX_.resize(bestX_.size());

    //2.
    if (minX < maxX)
    {
        std::fill(minX_.begin(), minX_.end(), minX);
        std::fill(maxX_.begin(), maxX_.end(), maxX);
    }
    else
    {
        std::fill(minX_.begin(), minX_.end(), maxX);
        std::fill(maxX_.begin(), maxX_.end(), minX);
    }
    
    return true;
}

bool BaseFun::setXRange(const VectorXd_t &minX, const VectorXd_t &maxX)
{
    //1.
    if (minX.size() != maxX.size())
    {
        LogError("变量上下限维度不一致,上限维度{},下限维度{}", maxX.size(), minX.size());
        return false;
    }
    else if (minX.size() != bestX_.size())
    {
        LogError("上下限维度{}与变量维度{}不一致", minX.size(), bestX_.size());
        return false;
    }

    //2.
    minX_ = minX;
    maxX_ = maxX;
    return true;
}

void BaseFun::normVar([[maybe_unused]] VectorXd_t &x)
{

}

void BaseFun::calcErrorFun([[maybe_unused]]const VectorXd_t &x, [[maybe_unused]]VectorXd_t &y)
{

}

void BaseFun::calcJacobiDiff([[maybe_unused]]const VectorXd_t &x, [[maybe_unused]]MatrixXd_t &jacobi)
{

}

void BaseFun::write(File &fw) const
{
    writeBase(fw);
}

void BaseFun::read(File &fr)
{
    readBase(fr);
}

void BaseFun::writeBase(File &fw) const
{
   fw.write<uint16_t>(static_cast<uint16_t>(type_));

   fw.write<uint32_t>(id_);
   fw.write<uint8_t>(static_cast<uint8_t>(level_));

   fw.writeString(name_);
   fw.writeString(description_);

   fw.write<value_t>(passY_);
   fw.write<value_t>(bestY_);

   Help::writeVecValue(fw, bestX_);
   Help::writeVecValue(fw, minX_);
   Help::writeVecValue(fw, maxX_);
}

void BaseFun::readBase(File &fr)
{
    id_          = fr.read<uint32_t>();
    level_       = static_cast<DifficultyLevel_E>(fr.read<uint8_t>());
    name_        = fr.readString();
    description_ = fr.readString();
    passY_       = fr.read<value_t>();
    bestY_       = fr.read<value_t>();

    Help::readVecValue(fr, bestX_);
    Help::readVecValue(fr, minX_);
    Help::readVecValue(fr, maxX_);
}

VectorXd_t initData(const vecValue_t &data)
{
    VectorXd_t x(data.size());
    std::copy(data.begin(), data.end(), x.data());
    return x;
}

}